package tgc.edu.ljc.web.controller;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import tgc.edu.ljc.custom.AjaxResult;
import tgc.edu.ljc.custom.CommonController;
import tgc.edu.ljc.custom.TablePageable;
import tgc.edu.ljc.custom.TimeUtils;
import tgc.edu.ljc.entity.DataSum;
import tgc.edu.ljc.entity.SysDept;
import tgc.edu.ljc.entity.SysFile;
import tgc.edu.ljc.entity.SysRole;
import tgc.edu.ljc.entity.SysUser;
import tgc.edu.ljc.security.UserUtils;
import tgc.edu.ljc.service.DataSumService;
import tgc.edu.ljc.service.SysDeptService;
import tgc.edu.ljc.service.SysFileService;
import tgc.edu.ljc.web.form.SysFileForm;

@Controller
@RequestMapping(value = "/sysFile")
public class SysFileController extends CommonController<SysFile, Integer, SysFileForm> {
	@Autowired
	private SysFileService fileService;
	@Autowired
	private DataSumService datasumService;
	@Autowired
	private UserUtils userUtils;
	@Autowired
	private SysDeptService deptService;
	@Override
	public Object page(TablePageable pageParam, SysFileForm form) {
		PageRequest pageable = pageParam.bulidPageRequest();
		SysUser user = userUtils.getUser();
		// 查询当前用户查看权限
		boolean isAdmin = false;
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			//List<SysDept> list1 = new ArrayList<>();
			//List<SysDept> list = fileService.setSysDepts(user.getDept(),list1);
			//spec = buildSpec2(form, user).and(buildSpec4(list));
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageable);
		return AjaxResult.bulidPageResult(page);
	}

	@Override
	public Object delete(Integer id) {
		try {
			SysUser user = userUtils.getUser();
			boolean b = false;
			SysFile findById = fileService.findById(id);
			for (SysRole r : user.getRoles()) { // 判断当前用户是否具有管理员权限
				if (r.getCode().equals("ROLE_ADMIN")) {
					b = true;
				}
			}
			if (!user.getUsername().equals(findById.getUploadsUsername()) && !b) {
				return new AjaxResult(false, "删除失败，您没有该权限！");
			} else {
				findById.setIsUsed(false);
				findById.setDelTime(TimeUtils.getStringDate());
				fileService.save(findById);
				return new AjaxResult("数据删除成功");
			}
		} catch (Exception e) {
		}
		return new AjaxResult("数据删除失败");
	}

	@Override
	public void edit(SysFileForm form, ModelMap map) throws InstantiationException, IllegalAccessException {
		List<DataSum> dataSums = datasumService.findAll();
		List<DataSum> fileType = null, fileNature = null;
		for (int i = 0; i < dataSums.size(); i++) {
			if (dataSums.get(i).getParentId() == null) {
				switch (dataSums.get(i).getCode()) {
				case "DICT_FILE_TYPE":
					fileType = dataSums.get(i).getChildren();
					break;
				case "DICT_FILE_DOCUMENTS":
					fileNature = dataSums.get(i).getChildren();
					break;
				default:
					break;
				}
			}
		}
		if (form.getId() != null) {
			boolean edit = true;
			map.put("edit", edit);
		}else {
			boolean edit = false;
			map.put("edit", edit);
		}
		map.put("fileType", fileType);
		map.put("fileNature", fileNature);
		super.edit(form, map);
	}

	@Override
	public Object save(SysFileForm form) {
		boolean savefile=true;
		List<String> filenames=new ArrayList<>();
		if (form.getId() == null) {
			for (MultipartFile file : form.getFile2()) {
				form.setFile(file);
				boolean savefile2 = fileService.savefile(form);
				if(!savefile2) {
					savefile=false;
					filenames.add(file.getOriginalFilename());
				}
			}
			if (savefile) {
				return new AjaxResult("文件上传成功");
			} else {
				return new AjaxResult(false,filenames.toString()+ "文件上传失败");
			}
		} else {
			SysUser user = userUtils.getUser();
			SysFile findById = fileService.findById(form.getId());
			if (!user.getUsername().equals(findById.getUploadsUsername())) {
				return new AjaxResult(false, "修改失败，您没有修改该文件的权限！");
			}
			fileService.mySave(findById, form);
			return new AjaxResult("保存成功");
		}
	}

	// 判断该文件是否损坏
	@RequestMapping(value = "/download")
	@ResponseBody
	public Object download(String fileUuid, HttpServletRequest request, HttpServletResponse response) {
		boolean savefile = fileService.download(fileUuid, request, response);
		if (savefile) {
			return fileUuid;
		} else {
			return new AjaxResult(false, "下载失败！文件损坏或不存在！");
		}
	}

	@RequestMapping(value = "/download2")
	@ResponseBody
	public void download2(String fileUuid, HttpServletRequest request, HttpServletResponse response) {
		fileService.download(fileUuid, request, response);
	}

	public Specification<SysFile> buildSpec1(SysFileForm form) {
		
		Specification<SysFile> spec = new Specification<SysFile>() {
			private static final long serialVersionUID = 8351493853179634432L;
			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules=new HashSet<>();
				rules.add(cb.equal(root.get("isUsed"), true));

				if(StringUtils.hasText(form.getUserDept())) { 
					Predicate userDept = cb.equal(root.get("userDept").get("id"),Integer.valueOf(form.getUserDept()));
					rules.add(userDept);
				}
				if(StringUtils.hasText(form.getFileTitle())) { 
					Predicate fileTitle = cb.like(root.get("fileTitle"),"%"+form.getFileTitle()+"%");
					rules.add(fileTitle);
				}
				if(form.getFileType()!=null) {
					rules.add(cb.equal(root.get("fileType").get("id"), form.getFileType()));
				}
				
				if(StringUtils.hasText(form.getFileName())) {
					Predicate name = cb.like(root.get("fileName"), "%"+form.getFileName()+"%");
					rules.add(name);
				}
				if(StringUtils.hasText(form.getFileUser())) {
					Predicate difficultylevel = cb.like(root.get("uploadsName"), "%"+form.getFileUser()+"%");
					rules.add(difficultylevel);
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		if(StringUtils.hasText(form.getSearch())) {
			return spec.and(buildSpec7(form.getSearch()));
		}else {
			return spec;
		}
	}

	public Specification<SysFile> buildSpec2(SysFileForm form, SysUser user) {

		Specification<SysFile> spec = new Specification<SysFile>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				//rules.add(cb.equal(root.get("isUsed"), true));
				if(StringUtils.hasText(form.getUserDept())) { 
					Predicate userDept = cb.equal(root.get("userDept").get("id"),Integer.valueOf(form.getUserDept()));
					rules.add(userDept);
				}
				if(StringUtils.hasText(form.getFileTitle())) { 
					Predicate fileTitle = cb.like(root.get("fileTitle"),"%"+form.getFileTitle()+"%");
					rules.add(fileTitle);
				}
				if(StringUtils.hasText(form.getFileName())) {
					Predicate name = cb.like(root.get("fileName"), "%"+form.getFileName()+"%");
					rules.add(name);
				}
				if(StringUtils.hasText(form.getFileUser())) {
					Predicate difficultylevel = cb.like(root.get("uploadsUsername"), "%"+form.getFileUser()+"%");
					rules.add(difficultylevel);
				}
				if(form.getFileType()!=null) {
					rules.add(cb.equal(root.get("fileType").get("id"), form.getFileType()));
				}

				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		Specification<SysFile> spec3 = buildSpec3();
		Specification<SysFile> spec5 = buildSpec5(user);
		if(StringUtils.hasText(form.getSearch())) {
			return spec.and(spec3).and(spec5).and(buildSpec7(form.getSearch()));
		}else {
			return spec.and(spec3).and(spec5);
		}
	}

	public Specification<SysFile> buildSpec3() {

		Specification<SysFile> spec = new Specification<SysFile>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				rules.add(cb.equal(root.get("isUsed"), true));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}
	public Specification<SysFile> buildSpec4(List<SysDept> list) {
		
		Specification<SysFile> spec = new Specification<SysFile>() {
			
			
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				for (SysDept sysDept : list) {
					rules.add(cb.equal(root.get("userDept").get("id"), sysDept.getId()));
				}
				return cb.or(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}
	public Specification<SysFile> buildSpec5(SysUser user) {
		
		Specification<SysFile> spec = new Specification<SysFile>() {
			
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				System.out.println(root.get("uploadsUsername")+":"+user.getUsername());
				rules.add(cb.equal(root.get("uploadsUsername"), user.getUsername())); // 该用户自己上传的文件
				rules.add(cb.equal(root.get("fileNature").get("name"), "公共")); // 公共的文件
				return cb.or(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec.or(buildSpec6());
	}
	
	public Specification<SysFile> buildSpec6(){
		Specification<SysFile> spec=new Specification<SysFile>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules=new HashSet<>();
				rules.add(cb.equal(root.get("fileNature").get("code"), "DICT_TOPANDSAME"));//部门共享
				Integer id = userUtils.getUser().getDept().getId();
				List<Integer> ids = deptService.findAllChildrenId(id);
				rules.add(root.get("userDept").get("id").in(ids));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
			
		};
		
		return spec;
	}
	
	public Specification<SysFile> buildSpec7(String search){
		@SuppressWarnings("serial")
		Specification<SysFile> spec=new Specification<SysFile>() {

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules=new HashSet<>();
				if(StringUtils.hasText(search)) {
					rules.add(cb.like(root.get("fileTitle"), "%"+search+"%"));
					rules.add(cb.like(root.get("fileRemark"), "%"+search+"%"));
					rules.add(cb.like(root.get("updateTime"), "%"+search+"%"));
					rules.add(cb.like(root.get("uploadsName"), "%"+search+"%"));
				}
				return cb.or(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}
	
	/***
	 * 图片缩略图列表
	 * @param modelMap
	 * @return
	 */
	@RequestMapping(value="/pictureList")
	public String pictureList(String search,ModelMap modelMap) {
		return "sysFile/pictureList";
	}
	
	/***
	 * 视频缩略图列表
	 * @param search
	 * @param modelMap
	 * @return
	 */
	@RequestMapping(value="/videoList")
	public String videoList(String search,ModelMap modelMap) {
		return "sysFile/videoList";
	}
	/***
	 * 音频缩略图列表
	 * @param search 搜索字段内容
	 * @return
	 */
	@RequestMapping(value="/voiceList")
	public String voiceList(String search) {
		return "sysFile/voiceList";
	}
	/***
	 * office文件缩略图列表
	 * @param search 搜索字段内容
	 * @return
	 */
	@RequestMapping(value="/officeList")
	public String officeList(String search) {
		return "sysFile/officeList";
	}
	
	
	/****
	 * 下载缩略图
	 * @param fileUuid
	 * @param response
	 */
	@RequestMapping(value="/download3")
	@ResponseBody
	public void download3(String fileUuid,HttpServletResponse response) {
		fileService.downloadShortImage(fileUuid, response);
	}
	
	@RequestMapping(value="/imagePage")
	@ResponseBody
	public Object imagePage(Pageable pageRequest,String search) {
		SysFileForm form=new SysFileForm();
		form.setFileType(7);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user = userUtils.getUser();
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}

	@RequestMapping(value="/videoPage")
	@ResponseBody
	public Object videoPage(Pageable pageRequest,String search) {
		SysFileForm form=new SysFileForm();
		form.setFileType(8);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user = userUtils.getUser();
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}
	
	@RequestMapping(value="/voicePage")
	@ResponseBody
	public Object voicePage(Pageable pageRequest,String search) {
		SysFileForm form=new SysFileForm();
		form.setFileType(9);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user = userUtils.getUser();
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}

	
	@RequestMapping(value="/officePage")
	@ResponseBody
	public Object officePage(Pageable pageRequest,String search) {
		SysFileForm form=new SysFileForm();
		form.setFileType(2);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user = userUtils.getUser();
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}

}
